package com.thientan.export

import ar.com.fdvs.dj.domain.Style
import ar.com.fdvs.dj.domain.builders.ColumnBuilder
import ar.com.fdvs.dj.domain.builders.ColumnBuilderException
import ar.com.fdvs.dj.domain.builders.FastReportBuilder
import ar.com.fdvs.dj.domain.constants.Border
import ar.com.fdvs.dj.domain.constants.Font
import ar.com.fdvs.dj.domain.constants.HorizontalAlign;
import ar.com.fdvs.dj.domain.constants.Transparency

import net.sf.jasperreports.engine.JRException
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource

import java.awt.Color
import java.io.IOException
import java.util.List

import javax.servlet.http.HttpServletResponse

import com.thientan.export.exceptions.ExportException


/**
 * Utility to handle building a report and streaming to the client.
 *
 */
public final class ExportHandlerImpl {
	private static final int EXPORT_COLUMN_WIDTH_DEFAULT = 300
	private static final int EXPORT_HEADER_HEIGHT = 15
	private static final Color EXPORT_HEADER_COLOR = new Color(211,211,211)//LightGrey
	
    String exportTemplateFilePath
    // If we're using a template file for exporting, then we must pass exportParameterBuilder with its implementation.
    IExportParameterBuilder exportParameterBuilder

    /**
     * Handle building the report, use list of column information to define report columns.
     * @param filename
     * @param basePath
     * @param docType
     * @param exportList
     * @param colDefinitions
     * @param sheetNames : By default it will be null
     * @throws EntityBusinessException 
     */
    public void exportHandler(String filename, String basePath, ExportType docType, List<Object> exportList,
    List<ReportColumnInformation> colDefinitions, String[] sheetNames = null) throws ExportException {
        try {
            FastReportBuilder rb = new FastReportBuilder()
            // If export following by a template, apply that template for FastReportBuilder
            if(exportTemplateFilePath){
                rb.setTemplateFile(exportTemplateFilePath)
            }
            rb.setWhenNoDataAllSectionNoDetail() // Build file with empty content when no data found

            for(ReportColumnInformation rci : colDefinitions) {
                rb.addColumn(ColumnBuilder.getNew().setColumnProperty(rci.getPropertyName(),
                        rci.getColumnClass().getName()).setTitle(rci.getColumnTitle()).build())
            }

            buildReport(filename, basePath, docType, exportList, rb, sheetNames)

        } catch(ColumnBuilderException e) {
            throw new ExportException("Cannot make column definitions")
        }
    }

    /**
     * Handle building the report, use arrays to define report columns.
     * @param filename
     * @param basePath
     * @param docType
     * @param exportList
     * @param colNames
     * @param colType
     * @param colTitles
     * @throws ExportException
     */
    public void exportHandler(String filename, String basePath, ExportType docType, List<Object> exportList,
    String[] colNames, Class<?>[] colType, String[] colTitles, int[] colWidths,
    String[] sheetNames = null)	throws ExportException {
        try {
            FastReportBuilder rb = new FastReportBuilder()
            // If export following by a template, apply that template for FastReportBuilder
            if(exportTemplateFilePath){
                rb.setTemplateFile(exportTemplateFilePath)
            }
            rb.setWhenNoDataAllSectionNoDetail()    // Build file with empty content when no data found
            int size = colNames.length
            if (colWidths == null) { // If colWidth is not defined, it will be initialized with default value
                colWidths = new int[size]
                for (int i = 0; i < size; i++) {
                    colWidths[i] = EXPORT_COLUMN_WIDTH_DEFAULT
                }
            }
			
			// Create headerStyle
			Style headerStyle = new Style()
			headerStyle.setBorderTop(Border.THIN)
			headerStyle.setBorderBottom(Border.THIN)
			headerStyle.setBorderLeft(Border.THIN)
			headerStyle.setBorderRight(Border.THIN)
			headerStyle.setBackgroundColor(EXPORT_HEADER_COLOR)
			headerStyle.setTransparency(Transparency.OPAQUE)
			headerStyle.setFont(Font.ARIAL_MEDIUM_BOLD)
			
			// for pdf files, align center for header and content cells.
			if(docType == ExportType.PDF){
				headerStyle.setHorizontalAlign(HorizontalAlign.CENTER)
			}
			
            for(int i=0 ; i<size ; i++) {
				// Create contentStyle
				Style contentStyle = new Style()
				contentStyle.setBorderTop(Border.THIN)
				contentStyle.setBorderBottom(Border.THIN)
				contentStyle.setBorderLeft(Border.THIN)
				contentStyle.setBorderRight(Border.THIN)
				
				// Specify for export PhieuThu
				if(docType == ExportType.PDF){
					contentStyle.setHorizontalAlign(HorizontalAlign.CENTER)
				}
				
				ColumnBuilder columnBuilder = ColumnBuilder.getNew().setColumnProperty(colNames[i],
                        colType[i].getName()).setTitle(colTitles[i]).setWidth(colWidths[i]).setHeaderStyle(headerStyle);				
				// Set number format pattern and alignment for bigdecimal column type
                if (colType[i].getName().equals(BigDecimal.class.getName())) {
					columnBuilder.setPattern("#,##0;-#,##0");
					contentStyle.setHorizontalAlign(HorizontalAlign.RIGHT)
				}
				columnBuilder.setStyle(contentStyle);
				rb.addColumn(columnBuilder.build());
            }
			
			rb.setHeaderHeight(EXPORT_HEADER_HEIGHT)

            buildReport(filename, basePath, docType, exportList, rb, sheetNames)

        } catch(ColumnBuilderException e) {
            throw new ExportException("Cannot make column definitions", e)
        }
    }

    public void buildReport(String filename, String basePath, ExportType docType, List<Object> exportList,
    FastReportBuilder rb , String[] sheetNames) throws ExportException{
        try {
            ExportRequest er = new ExportRequest()
            er.setFileName(filename)
            er.setBasePath(basePath)
            er.setType(docType)
            // Export the custom sheet name
            if(sheetNames){
                er.putAdditionProperties(ReportPropertyConstants.SHEET_NAMES, sheetNames)
            }
            // Set parameters before export.
            if(exportTemplateFilePath && exportParameterBuilder){
                exportParameterBuilder.prepareParametersBeforeExport(er)
            }
            JRBeanCollectionDataSource dt = new JRBeanCollectionDataSource(exportList)

            ExportManager.exportOXYC (rb, dt, er)
        } catch(JRException e) {
            throw new ExportException("Cannot build report", e)
        } catch(IOException e) {
            throw new ExportException("Cannot write out report", e)
        }
    }

    /**
     * Send a file to the client.
     * @param response
     * @param fullpath
     */
    public void sendFile(HttpServletResponse response, String fullpath, String clientFileName) {
        def file = new File(fullpath)
        response.setContentType("application/octet-stream")
        response.setHeader("Content-disposition", "attachment;filename=${clientFileName}")
		// Open to read content, and after that close stream to allow delete file.
        response.outputStream << file.newInputStream()
    }
}
